"""
实现一个栈，该栈带有出栈（pop）、入栈（push）、取最小元素（get_min）3个方法。
要保证这3个方法的时间复杂度都是O（1）。


4   9   7   3   8   5
栈顶：4
栈底：5
调用 get_min 方法，返回最小值 3
"""


class MinStack:
    """解法
    1.设原有的栈叫作栈A，此时创建一个额外的“备胎”栈B，用于辅助栈A。

    2.当第1个元素进入栈A时，让新元素也进入栈B。这个唯一的元素是栈A的当前最小值。

    3.之后，每当新元素进入栈A时，比较新元素和栈A当前最小值的大小，
    如果小于栈A当前最小值，则让新元素进入栈B，此时栈B的栈顶元素就是栈A当前最小值。

    4.每当栈A有元素出栈时，如果出栈元素是栈A当前最小值，则让栈B的栈顶元素也出栈。
    此时栈B余下的栈顶元素所指向的，是栈A中原本第2小的元素，代替刚才的出栈元素成为栈A的当前最小值。（备胎转正。）

    5.当调用 get_min 方法时，返回栈B的栈顶所存储的值，这也是栈A的最小值。

    显然，这个解法中进栈、出栈、取最小值的时间复杂度都是 O（1），最坏情况空间复杂度是 O（n）。
    """

    def __init__(self):
        self.main_stack = []
        self.min_stack = []

    def push(self, element):
        self.main_stack.append(element)
        # 若辅助栈为空或者新元素的值小于或等于辅助栈栈顶元素的值，将新元素压入辅助栈
        if len(self.min_stack) == 0 or element <= self.min_stack[len(self.min_stack) - 1]:
            self.min_stack.append(element)

    def pop(self):
        # 如果出栈元素和辅助栈顶元素的值相等，辅助栈的栈顶元素出栈
        if self.main_stack[len(self.main_stack) - 1] == self.min_stack[len(self.min_stack) - 1]:
            self.min_stack.pop()
        return self.main_stack.pop()

    def get_min(self):
        if len(self.main_stack) == 0:
            return None
        return self.min_stack[len(self.min_stack) - 1]


if __name__ == '__main__':
    my_stack = MinStack()
    my_stack.push(4)
    my_stack.push(9)
    my_stack.push(7)
    my_stack.push(3)
    my_stack.push(8)
    my_stack.push(5)
    print(my_stack.get_min())
    my_stack.pop()
    my_stack.pop()
    my_stack.pop()
    print(my_stack.get_min())
